//-----------------------------------------------------------------------------
//	file: spi_fsm.v
//	breif:
//		状态机控制
//-----------------------------------------------------------------------------
module spi_fsm  #(
	parameter	WAIT_CNT_WIDTH = 4,
	parameter	WAIT_CNT_CYCLE = 4'd15
)
(
	input		clk,
	input		reset,
	input		enable,
	input		stop,
	output	reg	working,
	output	reg	load,
	output	reg	pick,
	output	reg	nss
);

// parameter state
localparam	STATE_IDLE	= 6'b00_0001;
localparam	STATE_WAIT1	= 6'b00_0010;
localparam	STATE_LOAD	= 6'b00_0100;
localparam	STATE_START	= 6'b00_1000;
localparam	STATE_WAIT2	= 6'b01_0000;
localparam	STATE_STOP	= 6'b10_0000;

// register
reg		[5:0] state;
reg		[WAIT_CNT_WIDTH-1:0] cnt;

// fsm
always @(posedge clk or negedge reset)
	if (reset == 1'b0)
		state <= STATE_IDLE;
	else case (state)
		STATE_IDLE:
			if (enable == 1'b1)
				state <= STATE_WAIT1;
		STATE_WAIT1:
			if (cnt == WAIT_CNT_CYCLE)
				state <= STATE_LOAD;
		STATE_LOAD:
			state <= STATE_START;
		STATE_START:
			if (stop == 1'b1)
				state <= STATE_WAIT2;
		STATE_WAIT2:
			if (cnt == WAIT_CNT_CYCLE)
				state <= STATE_STOP;
		STATE_STOP:
			if (enable == 1'b1)
				state <= STATE_WAIT1;
			else
				state <= STATE_IDLE;
		default:
			state <= STATE_IDLE;
	endcase

// wait
always @(posedge clk or negedge reset)
	if (reset == 1'b0)
		cnt <= {WAIT_CNT_WIDTH{1'b0}};
	else if (cnt == WAIT_CNT_CYCLE)
		cnt <= {WAIT_CNT_WIDTH{1'b0}};
	else if ((state == STATE_WAIT1) || (state == STATE_WAIT2))
		cnt <= cnt + 1'b1;

// load
always @(posedge clk or negedge reset)
	if (reset == 1'b0)
		load <= 1'b0;
	else if (state == STATE_LOAD)
		load <= 1'b1;
	else
		load <= 1'b0;

// pick
always @(posedge clk or negedge reset)
	if (reset == 1'b0)
		pick <= 1'b0;
	else if ((state == STATE_WAIT2) && (|cnt == 1'b0))
		pick <= 1'b1;
	else
		pick <= 1'b0;

// working
always @(posedge clk or negedge reset)
	if (reset == 1'b0)
		working <= 1'b0;
	else if (stop == 1'b1)
		working <= 1'b0;
	else if (state == STATE_START)
		working <= 1'b1;

// nss
always @(posedge clk or negedge reset)
	if (reset == 1'b0)
		nss <= 1'b1;
	else if (state == STATE_IDLE)
		nss <= 1'b1;
	else
		nss <= 1'b0;

endmodule
